package com.ziyueyuwen.xiniao.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ziyueyuwen.xiniao.bean.ao.LessonSaveAO;
import com.ziyueyuwen.xiniao.bean.ao.LessonUpdateVO;
import com.ziyueyuwen.xiniao.bean.ao.TransferStudentAO;
import com.ziyueyuwen.xiniao.bean.*;
import com.ziyueyuwen.xiniao.bean.group.MessageDetailGroup;
import com.ziyueyuwen.xiniao.bean.homework.HomeworkRecordStatusDO;
import com.ziyueyuwen.xiniao.bean.page.PageData;
import com.ziyueyuwen.xiniao.bean.query.LessonQuery;
import com.ziyueyuwen.xiniao.bean.report.ZyStudentLessonReport;
import com.ziyueyuwen.xiniao.bean.vo.*;
import com.ziyueyuwen.xiniao.dao.*;
import com.ziyueyuwen.xiniao.enums.HomeworkStatusEnum;
import com.ziyueyuwen.xiniao.enums.MessageTypeEnum;
import com.ziyueyuwen.xiniao.enums.UserIdentityEnum;
import com.ziyueyuwen.xiniao.service.*;
import com.ziyueyuwen.xiniao.service.baseservice.lesson.ZyClassLessonService;
import com.ziyueyuwen.xiniao.service.baseservice.report.ReportBaseService;
import com.ziyueyuwen.xiniao.service.baseservice.user.ZyClassUserService;
import com.ziyueyuwen.xiniao.service.report.ReportService;
import com.ziyueyuwen.xiniao.util.DateUtil;
import com.ziyueyuwen.xiniao.util.EEOUtil;
import com.ziyueyuwen.xiniao.util.PageDataUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.ziyueyuwen.xiniao.enums.MessageTypeEnum.MESSAGE_LESSON_URL_REPLAY;
import static com.ziyueyuwen.xiniao.util.DateUtil.DEFAULT_FORMAT_PATTERN_2;
import static com.ziyueyuwen.xiniao.util.DateUtil.DEFAULT_FORMAT_PATTERN_3;

/**
 * @author wancheng  on 2018/12/21.
 */
@Service
public class LessonServiceImpl implements LessonService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    ZyClassLessonInfoMapper zyClassLessonInfoMapper;
    @Autowired
    ZyClassInfoMapper zyClassInfoMapper;
    @Autowired
    ZyCourseInfoMapper zyCourseInfoMapper;
    @Autowired
    ZyMessageDetailsMapper zyMessageDetailsMapper;
    @Autowired
    HomeworkRecordService homeworkRecordService;
    @Autowired
    ZyLessonMessageTaskMapper zyLessonMessageTaskMapper;
    @Autowired
    ClassUserService classUserService;
    @Autowired
    ZyClassLessonService zyClassLessonService;
    @Autowired
    LessonUserService lessonUserService;
    @Autowired
    ZyClassUserService zyClassUserService;
    @Autowired
    UserService userService;
    @Autowired
    TransferStudentService transferStudentService;
    @Autowired
    ReportService reportService;

    @Override
    public List<ZyClassLessonInfo> getClassLesson(Integer classId) {
        ZyClassLessonInfo param = new ZyClassLessonInfo();
        param.setClassId(classId);
        List<ZyClassLessonInfo> res = zyClassLessonInfoMapper.select(param);
        return res;
    }

    @Override
    public Map<String, Object> getStudentLessonByClassId(Integer classId, String studentAccount) {
        ZyClassInfo zyClassInfo = zyClassInfoMapper.selectByPrimaryKey(classId);
        ZyCourseInfo zyCourseInfo = zyCourseInfoMapper.selectByPrimaryKey(zyClassInfo.getCourseId());
        List<ZyClassLessonInfo> classLesson = zyClassLessonService.getLessonByClassIdAndStudent(classId,studentAccount);
        if (CollectionUtils.isEmpty(classLesson)){
            Map<String, Object> completeMap = new HashMap<>(4);
            completeMap.put("className", zyClassInfo.getClassName());
            completeMap.put("courseName", zyCourseInfo.getCourseName());
            return completeMap;
        }
        List<ZyClassLessonInfo> transferLesson = zyClassLessonService.getTransferLesson(classId, studentAccount);
        //如果有插班课 则替换原课节
        if (CollectionUtils.isNotEmpty(transferLesson)) {
            Map<Integer, ZyClassLessonInfo> classLessonIndexMap = classLesson.stream().collect(Collectors.toMap(ZyClassLessonInfo::getLessonIndex, l -> l));
            Map<Integer, ZyClassLessonInfo> transferLessonIndexMap = transferLesson.stream().collect(Collectors.toMap(ZyClassLessonInfo::getLessonIndex, l -> l));
            transferLessonIndexMap.entrySet().forEach(
                    e -> {
                        classLessonIndexMap.put(e.getKey(),e.getValue());
                    });
            classLesson = classLessonIndexMap.entrySet().stream().map(e->e.getValue()).collect(Collectors.toList());
        }
        List<Integer> lessonIds = classLesson.stream().map(ZyClassLessonInfo::getId).collect(Collectors.toList());

        List<ZyLessonVO> lessonVOs = zyClassLessonInfoMapper.getStudentLesson(lessonIds);

        lessonVOs.forEach(this::formatDate);
        Map<Boolean, List<ZyLessonVO>> map = lessonVOs.stream().collect(Collectors.groupingBy(ZyLessonVO::getIfComplete));
        Map<String, Object> completeMap = new HashMap<>(4);
        completeMap.put("className", zyClassInfo.getClassName());
        completeMap.put("courseName", zyCourseInfo.getCourseName());
        completeMap.put("previous", map.get(true));
        completeMap.put("next", map.get(false));
        return completeMap;
    }

    @Override
    public ZyLessonVO getStudentLessonTaskByLessonId(Integer lessonId, String userAccount) {
        ZyLessonVO zyLessonVO = zyClassLessonInfoMapper.getStudentLessonTaskByLessonId(lessonId);
        if (zyLessonVO == null) {
            return null;
        }
        formatDate(zyLessonVO);
        Integer finalLessonId = lessonId;
        zyLessonVO.getTask().forEach(
                t -> {
                    ZyMessageDetails param = new ZyMessageDetails();
                    param.setMessageType(t.getType());
                    param.setLessonId(t.getLessonId());
                    param.setUserAccount(userAccount);
                    ZyMessageDetails details = zyMessageDetailsMapper.selectOne(param);
                    if (details != null) {
                        t.setUrl(details.getMessageUrl());
                        t.setIfRetrieval(details.getIfReceiveConfirm());
                    } else {
                        //添加回放链接,剩下的前端获取连接
                        if (MESSAGE_LESSON_URL_REPLAY.equals(t.getType())) {
                            try {
                                ZyClassLessonInfo lesson = zyClassLessonInfoMapper.selectByPrimaryKey(finalLessonId);
                                ZyMessageDetails insert = new ZyMessageDetails();
                                insert.setIfReceiveConfirm(true);
                                insert.setConfirmTime(new Date());
                                insert.setUserAccount(userAccount);
                                insert.setLessonId(finalLessonId);
                                insert.setIfSendSuccess(true);
                                insert.setMessageType(MESSAGE_LESSON_URL_REPLAY);
                                insert.setUserIdentity(UserIdentityEnum.STUDENT);
                                insert.setCreateTime(new Date());
                                insert.setTaskId(t.getId());
                                insert.setMessageUrl(EEOUtil.getWebcastUrl(lesson.getEeoCourseId(), lesson.getEeoLessonId()));
                                zyMessageDetailsMapper.insertSelective(insert);
                                t.setUrl(insert.getMessageUrl());
                                t.setIfRetrieval(insert.getIfReceiveConfirm());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }

                });
        return zyLessonVO;
    }

    @Override
    public ZyLessonVO getClassAndCourseByLessonId(Integer lessonId) {
        return zyClassLessonInfoMapper.getLessonClassAndCourse(lessonId);
    }

    @Override
    public List<LessonUserMessageVO> lessonUserMessage(Integer lessonId) {
        ZyClassLessonInfo lesson = zyClassLessonInfoMapper.selectByPrimaryKey(lessonId);
        //学生的查看情况
        List<ZyMessageDetailsVO> detailsVOs = zyMessageDetailsMapper.getByLessonId(lessonId);
        Map<MessageDetailGroup, ZyMessageDetailsVO> detailsVOsMap = detailsVOs.stream().collect(Collectors.toMap(t -> new MessageDetailGroup(t.getUserAccount(), t.getMessageType()), ts -> ts));
        List<ZyClassUserVO> students = classUserService.getStudent(lesson.getClassId());
        List<LessonUserMessageVO> vos = new ArrayList<>();
        students.forEach(
                s -> {
                    LessonUserMessageVO lessonUserMessageVO = new LessonUserMessageVO();
                    lessonUserMessageVO.setUserAccount(s.getUserAccount());
                    lessonUserMessageVO.setUserName(s.getUserName());
                    vos.add(lessonUserMessageVO);
                    ZyMessageDetailsVO preview = detailsVOsMap.get(new MessageDetailGroup(s.getUserAccount(), MessageTypeEnum.MESSAGE_LESSON_INFLATED));
                    ZyMessageDetailsVO homework = detailsVOsMap.get(new MessageDetailGroup(s.getUserAccount(), MessageTypeEnum.MESSAGE_LESSON_HOMEWORK));
                    ZyMessageDetailsVO summarize = detailsVOsMap.get(new MessageDetailGroup(s.getUserAccount(), MessageTypeEnum.MESSAGE_LESSON_URL_SUMMARIZE));
                    ZyMessageDetailsVO replay = detailsVOsMap.get(new MessageDetailGroup(s.getUserAccount(), MESSAGE_LESSON_URL_REPLAY));
                    ZyMessageDetailsVO expansion = detailsVOsMap.get(new MessageDetailGroup(s.getUserAccount(), MessageTypeEnum.MESSAGE_LESSON_EXPANSION));
                    if (preview != null && preview.getIfReceiveConfirm()) {
                        lessonUserMessageVO.setPreview(true);
                    }
                    if (homework != null && homework.getIfReceiveConfirm()) {
                        HomeworkRecordStatusDO status = homeworkRecordService.getHomeworkStatus(s.getUserAccount(), lessonId);
                        lessonUserMessageVO.setHomework(status);
                    }
                    if (summarize != null && summarize.getIfReceiveConfirm()) {
                        lessonUserMessageVO.setSummarize(true);
                    }
                    if (replay != null && replay.getIfReceiveConfirm()) {
                        lessonUserMessageVO.setReplay(true);
                    }
                    if (expansion != null && expansion.getIfReceiveConfirm()) {
                        lessonUserMessageVO.setExpansion(true);
                    }
                }
        );
        return vos;
    }

    @Override
    public void confirmLessonTask(Integer lessonId, String userAccount, MessageTypeEnum typeEnum) throws Exception {

        ZyLessonMessageTask task = new ZyLessonMessageTask();
        task.setType(typeEnum);
        task.setLessonId(lessonId);
        task = zyLessonMessageTaskMapper.selectOne(task);
        ZyMessageDetails params = new ZyMessageDetails();
        params.setLessonId(lessonId);
        params.setUserAccount(userAccount);
        params.setMessageType(typeEnum);
        ZyMessageDetails details = zyMessageDetailsMapper.selectOne(params);
        if (details == null) {
            ZyMessageDetails insert = new ZyMessageDetails();
            insert.setIfReceiveConfirm(true);
            insert.setConfirmTime(new Date());
            insert.setUserAccount(userAccount);
            insert.setLessonId(lessonId);
            insert.setIfSendSuccess(false);
            insert.setMessageType(typeEnum);
            insert.setUserIdentity(UserIdentityEnum.STUDENT);
            insert.setCreateTime(new Date());
            if (task != null) {
                insert.setTaskId(task.getId());
            } else {
                insert.setTaskId(0);
            }
            zyMessageDetailsMapper.insertSelective(insert);
            return;
        }
        if (details.getIfReceiveConfirm()) {
            return;
        }
        ZyMessageDetails update = new ZyMessageDetails();
        update.setId(details.getId());
        update.setIfReceiveConfirm(true);
        update.setConfirmTime(new Date());
        zyMessageDetailsMapper.updateByPrimaryKeySelective(update);
    }

    @Override
    public void studentLessonReportDataCollect(Integer lessonId, String userAccount, MessageTypeEnum typeEnum) {
        try{
            ZyStudentLessonReport report = reportService.getReportMsgWhileIsNUllToSave(userAccount,lessonId);
            ZyStudentLessonReport update = new ZyStudentLessonReport();
            update.setId(report.getId());
            switch (typeEnum){
                case MESSAGE_LESSON_INFLATED:
                    update.setPreview(true);
                    break;
                case MESSAGE_LESSON_HOMEWORK:
                    HomeworkRecordStatusDO status = homeworkRecordService.getHomeworkStatus(userAccount, lessonId);
                    if (status.getIfMark()){
                        update.setHomework(HomeworkStatusEnum.CORRECTED);
                    }else{
                        HomeworkStatusEnum homeworkStatusEnum = status.getStatus();
                        update.setHomework(status.getStatus());
                    }
                    break;
                case MESSAGE_LESSON_URL_REPLAY:
                    update.setReplay(true);
                    break;
                case MESSAGE_LESSON_EXPANSION:
                    update.setExpansion(true);
                    break;
                case MESSAGE_LESSON_URL_SUMMARIZE:
                    update.setSummarize(true);
                    break;
                default:
                    break;
            }
            reportService.updateByPreKey(update);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public List<ZyClassLessonInfo> saveLesson(LessonSaveAO lessonSave, String createUserAccount) throws Exception {
        /**
         * 此处参数格式化
         */
        logger.info("添加排课,传入参数 lesson={},createUserAccount={}", JSON.toJSON(lessonSave), createUserAccount);
        ZyClassLessonInfo template = new ZyClassLessonInfo();
        template.setClassId(lessonSave.getClassId())
                .setSeatNum(lessonSave.getSeatNum())
                .setCreateTime(new Date())
                .setCreateUserAccount(createUserAccount);
        List<ZyClassLessonInfo> lessonInfoList = new LinkedList<>();
        for (String day : lessonSave.getDays()) {
            ZyClassLessonInfo lessonInfo = template.clone();
            lessonInfo.setClassDate(day);
            setLessonBeginTimeAndEndTime(lessonInfo, day + " " + lessonSave.getStartTime(), lessonSave.getDurationOfHour(), lessonSave.getDurationOfMinute());
            lessonInfoList.add(lessonInfo);
        }
        logger.info("格式化排课传入参数,lessonInfoList={}", JSON.toJSON(lessonInfoList));
        /**
         * 此处同步eeo 逻辑
         */
        Integer classId = lessonSave.getClassId();
        String teacherAccount = lessonSave.getTeacherAccount();
        //班级信息
        ZyClassInfo classInfo = zyClassInfoMapper.selectByPrimaryKey(classId);
        if (classInfo == null) {
            throw new Exception("班级不存在");
        }
        String teacherName = null;
        if (StringUtils.isBlank(lessonSave.getTeacherAccount())) {
            ZyClassUserVO teacher = classUserService.getTeacherByClassId(classId);
            if (teacher == null) {
                throw new Exception("该班级老师不存在");
            }
            teacherAccount = teacher.getUserAccount();
            teacherName = teacher.getUserName();
        } else {
            ZyUser teacher = userService.getByAccount(teacherAccount);
            teacherAccount = teacher.getUserAccount();
            teacherName = teacher.getUserName();
        }
        for (ZyClassLessonInfo l : lessonInfoList) {
            l.setEeoCourseId(classInfo.getEeoCourseId());
            l.setClassId(classId);
            //课节名称
            l.setClassLessonName(classInfo.getClassName());
            logger.info("组装课节名称,lessonInfo={}", JSON.toJSON(l));
        }

        /**
         * 此处 保存同步成功 课节
         */
        //添加eeo同步成功的课节
        List<ZyClassLessonInfo> eeoSyncError = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(lessonInfoList)) {
            eeoSyncError = zyClassLessonService.saveLessonBatch(lessonInfoList, lessonSave.getClassId(), lessonSave.getTeacherAccount(), lessonSave.getSeatNum());
        }

        //返回eeo 同步失败的课节
        return eeoSyncError;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteLesson(Integer lessonId, String deleteUserAccount) throws Exception {
        ZyClassLessonInfo lessonInfo = zyClassLessonService.getByPreKey(lessonId);
        logger.info("删除课节 lessonInfo={}",JSONObject.toJSON(lessonInfo));
        zyClassLessonService.deleteLesson(lessonId);
        //消息发送模板
        zyLessonMessageTaskMapper.deleteByLessonId(lessonId);
        //删除课节-用户相关信息
        lessonUserService.deleteLessonUser(lessonId);
        //删除插班生
        transferStudentService.deleteTransferStudent(lessonId);
        //eeo删除课节
        EEOUtil.delCourseClass(lessonInfo.getEeoCourseId(), lessonInfo.getEeoLessonId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject updateTransferStudent(TransferStudentAO transferStudent) throws Exception {
        //课节信息
        ZyClassLessonInfo lessonInfo = zyClassLessonInfoMapper.selectByPrimaryKey(transferStudent.getLessonId());
        List<ZyClassUserVO> students = classUserService.getStudent(lessonInfo.getClassId());
        //和数据库保存重复的学生
        List<ZyClassUserVO> repeat = students.stream().filter(s -> transferStudent.getStudentAccounts().contains(s.getUserAccount())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(repeat)) {
            throw new Exception("插班生中存在原班级的学生,学生姓名:" + repeat.stream().map(ZyClassUserVO::getUserName).collect(Collectors.joining(",")));
        }
        //原课节中的插班生
        List<ZyClassLessonTransfer> exist = transferStudentService.getTransferStudent(transferStudent.getLessonId());
        List<String> existAccount = exist.stream().map(ZyClassLessonTransfer::getUserAccount).collect(Collectors.toList());
        List<String> needInsert = transferStudent.getStudentAccounts().stream().filter(a -> !existAccount.contains(a)).collect(Collectors.toList());
        List<String> needDelete = existAccount.stream().filter(a -> !transferStudent.getStudentAccounts().contains(a)).collect(Collectors.toList());
        //新增插班生
        JSONArray insertRes = transferStudentService.addTransferStudent(transferStudent.getLessonId(), needInsert);
        //删除插班生
        JSONArray deleteRes = transferStudentService.deleteTransferStudent(transferStudent.getLessonId(), needDelete);
        JSONObject res = new JSONObject();
        res.put("insert", insertRes);
        res.put("delete", deleteRes);
        return res;
    }

    @Override
    public PageData getLessonForPage(LessonQuery query) {
        PageHelper.startPage(query.getPage(), query.getRows());
        PageHelper.orderBy(" begin_time asc ");
        List<LessonInfoPageVO> res = zyClassLessonInfoMapper.getClassLessonForPage(query.getClassId());
        PageInfo<LessonInfoPageVO> pageInfo = new PageInfo<>(res);
        PageData<LessonInfoPageVO> pageData = PageDataUtil.getPageData(pageInfo);
        pageData.getData().forEach(
                data -> {
                    data.setHourTimeOfString(DateUtil.date2Str(data.getBeginTime(), DEFAULT_FORMAT_PATTERN_2));
                    data.setDurationString(DateUtil.getDurationString(data.getDurationOfTime()));
                }
        );
        return pageData;
    }

    @Override
    public LessonInfoPageVO getByLessonId(Integer lessonId) {
        LessonInfoPageVO lesson = zyClassLessonInfoMapper.getLessonAndTeacherAndTransferStudents(lessonId);
        lesson.setDurationString(DateUtil.getDurationString(lesson.getDurationOfTime()));
        return lesson;
    }

    @Override
    public void updateLesson(LessonUpdateVO lessonUpdate, String updateUserAccount) throws Exception {
        logger.info("排课修改,传入参数 lesson={},updateUserAccount={}", JSON.toJSON(lessonUpdate), updateUserAccount);
        ZyClassLessonInfo lessonInfo = new ZyClassLessonInfo();
        lessonInfo.setId(lessonUpdate.getLessonId())
                .setSeatNum(lessonUpdate.getSeatNum())
                .setClassDate(lessonUpdate.getDay());
        setLessonBeginTimeAndEndTime(lessonInfo, lessonUpdate.getDay() + " " + lessonUpdate.getStartTime(), lessonUpdate.getDurationOfHour(), lessonUpdate.getDurationOfMinute());
        logger.info("格式化排课传入参数,lessonInfoList={}", JSON.toJSON(lessonInfo));
        zyClassLessonService.updateLesson(lessonInfo, lessonUpdate.getTeacherAccount());
    }

    @Override
    public List<ZyClassUserVO> getClassTeacher(Integer classId) {
        return zyClassUserService.getClassTeacher(classId);
    }

    @Override
    public void arrangeClassLesson(Integer classId) {
        zyClassLessonInfoMapper.arrangeClassLessonByClassId(classId);
    }

    @Override
    public ZyClassLessonInfo getLessonInfoByEeoClassId(Integer eeoClassId) {
        ZyClassLessonInfo lessonParam = new ZyClassLessonInfo();
        lessonParam.setEeoLessonId(eeoClassId);
        return zyClassLessonInfoMapper.selectOne(lessonParam);
    }

    /**
     * 格式化批量排课的结束时间
     *
     * @param lessonInfo
     * @param timeString
     * @param durationOfHour
     * @param durationOfMinute
     */
    private void setLessonBeginTimeAndEndTime(ZyClassLessonInfo lessonInfo, String timeString, Integer durationOfHour, Integer durationOfMinute) {
        Date begin = DateUtil.str2Date(timeString, DEFAULT_FORMAT_PATTERN_3);
        Date end = DateUtil.addHour(begin, durationOfHour);
        end = DateUtil.addMinute(end, durationOfMinute);
        lessonInfo.setBeginTime(begin);
        lessonInfo.setEndTime(end);
    }

    @Override
    public ZyClassLessonInfo getByPreKey(Integer lessonId) {
        return zyClassLessonInfoMapper.selectByPrimaryKey(lessonId);
    }

    private void formatDate(ZyLessonVO zyLessonVO) {
        String day = DateUtil.date2Str(zyLessonVO.getBeginTime(), DateUtil.DEFAULT_FORMAT_PATTERN_1);
        String begin = DateUtil.date2Str(zyLessonVO.getBeginTime(), DEFAULT_FORMAT_PATTERN_2);
        String end = DateUtil.date2Str(zyLessonVO.getEndTime(), DEFAULT_FORMAT_PATTERN_2);
        zyLessonVO.setDay(day);
        Date now = new Date();
        zyLessonVO.setTimeSlot(begin + "~" + end);
        if (now.after(zyLessonVO.getBeginTime())) {
            zyLessonVO.setIfComplete(true);
        } else {
            zyLessonVO.setIfComplete(false);
        }
    }
}
